using DataModels.Entities.Base;
using DataModels.Enums.WorkOrder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Services.AuthCore;
using System;
using System.IO;
using System.Net.Http.Headers;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Xml.Linq;

namespace WeChatServices
{
    public class WeChatMessageHandler
    {
        private readonly string _token;
        private readonly string _encodingAesKey;
        private readonly string _VXFWHappId;
        private readonly string _VXFWHappSecret;
        private readonly string miniProgramAppId;
        private readonly OauthService _oauthService;

        public WeChatMessageHandler(IConfiguration configuration, OauthService oauthService)
        {
            _token = configuration["AppSettings:WeChatFWHToken"];
            _encodingAesKey = configuration["AppSettings:WeChatFWHEncodingAesKey"];
            _VXFWHappId = configuration["AppSettings:VXFWHappId"];
            _VXFWHappSecret = configuration["AppSettings:VXFWHappSecret"];
            miniProgramAppId = configuration["AppSettings:VXappId"];

            _oauthService = oauthService;
        }

        /// <summary>
        /// 验证微信服务器签名
        /// </summary>
        public bool ValidateSignature(string signature, string timestamp, string nonce, string echostr)
        {
            var arr = new[] { _token, timestamp, nonce }.OrderBy(z => z).ToArray();
            var arrString = string.Join("", arr);
            var sha1 = SHA1.Create();
            var sha1Arr = sha1.ComputeHash(Encoding.UTF8.GetBytes(arrString));
            var enText = new StringBuilder();
            foreach (var b in sha1Arr)
            {
                enText.AppendFormat("{0:x2}", b);
            }
            return enText.ToString() == signature;
        }

        /// <summary>
        /// 处理微信消息推送（包括关注事件）
        /// </summary>
        public async Task<IActionResult> HandleMessageAsync(HttpContext context)
        {
            using (var reader = new StreamReader(context.Request.Body, Encoding.UTF8))
            {
                var xml = await reader.ReadToEndAsync();
                Console.WriteLine(xml);
                var doc = XDocument.Parse(xml);
                var root = doc.Root;

                // 获取消息类型
                var msgType = root.Element("MsgType")?.Value;

                // 处理事件消息
                if (msgType == "text")
                {
                    if (root.Element("Content")?.Value == "绑定小程序") {
                        await HandleUserSubscribeAsync(root.Element("FromUserName")?.Value, root);

                        return new ContentResult
                        {
                            Content = GetSuccessResponseXml(root, "绑定小程序成功"),
                            ContentType = "application/xml"
                        };
                    }
                }
                if (msgType == "event")
                {
                    var eventType = root.Element("Event")?.Value;
                    var openId = root.Element("FromUserName")?.Value;
                    // 处理关注事件
                    if (eventType == "subscribe")
                    {
                        // 这里获取到了用户的OpenID
                        await HandleUserSubscribeAsync(openId, root);
                        
                        // 返回成功响应
                        return new ContentResult
                        {
                            Content = GetSuccessResponseXml(root, "感谢关注!"),
                            ContentType = "application/xml"
                        };
                    }
                }

                // 默认返回成功响应
                return new ContentResult
                {
                    Content = GetSuccessResponseXml(root, ""),
                    ContentType = "application/xml"
                };
            }
        }

        /// <summary>
        /// 处理用户关注事件
        /// </summary>
        private async Task HandleUserSubscribeAsync(string openId, XElement root)
        {
            if (string.IsNullOrEmpty(openId))
                throw new ArgumentNullException(nameof(openId));

            // 1. 在这里可以将OpenID保存到数据库
            // 2. 可以调用微信用户信息接口获取更多用户信息
            // 3. 可以发送欢迎消息给用户

            try
            {
                Console.WriteLine($"用户: OpenID={openId}, 时间={DateTime.Now}");

                // TODO: 实现保存OpenID到数据库的逻辑
                // 2. 生成带 OpenID 的小程序路径（需 URL 编码）
                // 小程序目标页面：pages/welcome/index
                // 参数：openId = 用户 OpenID（建议加密传输，示例简化为明文）
                string encodedOpenId = HttpUtility.UrlEncode(openId);
                string miniProgramPath = $"/packageA/bind/wechatBind?openId={encodedOpenId}";

                // 3. 发送包含小程序跳转按钮的欢迎消息
                await SendWelcomeMessageWithMiniProgramAsync(openId, miniProgramPath);
            }
            catch (Exception ex)
            {
                // 处理异常
                Console.WriteLine($"处理用户关注事件出错: {ex.Message}");
            }
        }

        /// <summary>
        /// 发送带小程序跳转按钮的欢迎消息
        /// </summary>
        private async Task SendWelcomeMessageWithMiniProgramAsync(string openId, string miniProgramPath)
        {
            string appType = "fwh";
            string accessToken = await _oauthService.GetAccessToken(appType);
          
            // 验证AccessToken与小程序的关联关系（通过微信接口间接验证）
            var verifyClient = new HttpClient();
            var verifyResponse = await verifyClient.GetAsync(
                $"https://api.weixin.qq.com/cgi-bin/wxopen/wxamplinkget?access_token={accessToken}"
            );
            if (!verifyResponse.IsSuccessStatusCode)
            {
                Console.WriteLine("AccessToken对应的服务号与小程序关联关系异常");
                return; // 关联异常时直接终止，避免无效请求
            }

            // 2. 构造客服消息（包含小程序跳转按钮）
            // 构建包含小程序跳转的链接标签
            // 注意：href为备用链接，必须是HTTPS；data-*属性需正确设置
            string linkHtml = $@"<a href=""http://www.qq.com"" data-miniprogram-appid=""{miniProgramAppId}"" data-miniprogram-path=""{miniProgramPath}"">绑定小程序</a>";

            var welcomeMessage = new
            {
                touser = openId,
                msgtype = "text",
                text = new
                {
                    content = $"点击 {linkHtml}"
                }
            };

            //var welcomeMessage = new
            //{
            //    touser = openId,
            //    msgtype = "miniprogrampage",
            //    miniprogrampage = new
            //    {
            //        title = $"绑定小程序",
            //        appid = miniProgramAppId,
            //        pagepath = miniProgramPath,
            //        thumb_media_id= "test.jpg"  //临时图片。。
            //    }
            //};

            //图文链接 这种已不支持小程序
            //var welcomeMessage = new
            //{
            //    touser = openId, // 必须是原始OpenID（未编码的字符串）
            //    msgtype = "news", // 与内容严格匹配，不能是其他类型
            //    news = new
            //    {
            //        articles = new[] // 必须是数组（即使只有一个元素）
            //        {
            //            new
            //            {
            //                title = "欢迎进入小程序", // 长度不超过64字节
            //                description = "点击进入服务", // 长度不超过128字节
            //                url = "https://your-domain.com/backup", // 链接必须是HTTPS 点击后跳转外链
            //                picurl = "https://qiaosui.net/wyAssets/static/images/cm.jpg", // 图片必须是HTTPS且可访问 缩率图
            //                miniprogram = new
            //                {
            //                    appid =miniProgramAppId, // 必须是已关联的小程序AppID（无空格）
            //                    pagepath = "/pages/index/index?openId=xxx" // 必须以/开头，参数无特殊字符
            //                }
            //            }
            //        }
            //    }
            //};

            // 额外校验：序列化后检查是否有异常字符
            string messageJson = JsonConvert.SerializeObject(welcomeMessage, new JsonSerializerSettings
            {
                StringEscapeHandling = StringEscapeHandling.EscapeHtml // 确保HTML特殊字符正确转义
            });
            if (messageJson.Contains("\n") || messageJson.Contains("\r"))
            {
                Console.WriteLine("消息JSON包含换行符，可能导致解析失败");
                messageJson = messageJson.Replace("\n", "").Replace("\r", "");
            }
            // 3. 调用客服消息接口发送消息
            using (var httpClient = new HttpClient())
            {
                // 设置请求头的 Content-Type，指定 UTF-8 编码
                httpClient.DefaultRequestHeaders.Accept.Add(
                    new MediaTypeWithQualityHeaderValue("application/json")
                );

                // 构造请求内容时指定编码
                var content = new StringContent(
                    messageJson,  // 要发送的 JSON 字符串
                    Encoding.UTF8,  // 明确使用 UTF-8 编码
                    "application/json"
                );

                //确保开通客服功能和默认绑一个人
                //httpClient.DefaultRequestHeaders.IfModifiedSince = null;
                // httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                string apiUrl = $"https://api.weixin.qq.com/cgi-bin/message/custom/send?access_token={accessToken}";
                var response = await httpClient.PostAsync(apiUrl, content);
                string responseContent = await response.Content.ReadAsStringAsync();

                if (!response.IsSuccessStatusCode)
                {
                    Console.WriteLine($"发送失败：{response.StatusCode}，响应：{responseContent}");
                }
                else
                {
                    Console.WriteLine($"发送成功，响应：{responseContent}");
                }
            }            
        }

        public string GetTemplateMessageID(string TemplateName)
        {
            string TemplateMessageID = "";
            switch (TemplateName)
            {
                case "工单派送通知":
                    TemplateMessageID = "Yx3nRz2N1-mLVaVfpsUT92qixdeD_YCbSz2VVDaeG9s";
                    break;
                case "物业欠费通知":
                    TemplateMessageID = "LxA5thZTClVVN_j_FJ8RfkgV4Ka8WesEud4xYAqVSwo";
                    break;
                //case "工单派送通知":
                //    TemplateMessageID = "SYUOjGekf1EiJsZX7hywuH_HaLsQ3p-PisPE2hx5iYI";
                //    break;
                //case "物业欠费通知":
                //    TemplateMessageID = "YIJUh3KvZqV90mcU0IEctA_kmH6-zOvkLyMFjMo1lAY";
                //    break;
                
                default:
                    break;
            }
            return TemplateMessageID;
        }


        public string BuildTemplateMessageWithMultipleKeywords(
                 string openId,
                 string templateId,
                 string pagePath,
                 Dictionary<string, string> fieldValues, // 键：模板字段名（如character_string15），值：字段内容
                 string firstValue = "您好，有新消息！",
                 string remarkValue = "请及时查看",
                 string color = "#173177")
        {
            // 验证必填字段
            if (fieldValues == null || fieldValues.Count == 0)
                throw new ArgumentException("模板字段值不能为空");

            var data = new JObject
            {
                ["touser"] = openId,
                ["template_id"] = templateId,
                // 配置小程序跳转参数
                ["miniprogram"] = new JObject
                {
                    ["appid"] = miniProgramAppId, // 小程序AppID（必须与服务号关联）
                    ["pagepath"] = pagePath       // 跳转的小程序页面路径
                },
                ["data"] = new JObject()
            };

            var dataContent = (JObject)data["data"];

            // 添加first节点（如果模板包含）
            dataContent["first"] = new JObject
            {
                ["value"] = firstValue ?? " ", // 避免null，至少赋值空格
                ["color"] = color
            };

            // 循环添加所有业务字段（关键修复：确保每个字段都有值）
            foreach (var field in fieldValues)
            {
                // 确保值不为空（至少赋值一个空格）
                string fieldValue = string.IsNullOrEmpty(field.Value) ? " " : field.Value;

                dataContent[field.Key] = new JObject
                {
                    ["value"] = fieldValue,
                    ["color"] = color
                };
            }

            // 添加remark节点（如果模板包含）
            dataContent["remark"] = new JObject
            {
                ["value"] = remarkValue ?? " ", // 避免null
                ["color"] = color
            };

            return data.ToString();
        }

        /// <summary>
        /// 发送模板消息
        /// </summary>
        /// <param name="accessToken"></param>
        /// <param name="openId"></param>
        /// <param name="templateId"></param>
        /// <param name="dataJson"></param>
        /// <returns></returns>
        public async Task<string> SendTemplateMessage(string accessToken, string openId, string templateId, string dataJson)
        {
            string url = $"https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={accessToken}";
            using (HttpClient client = new HttpClient())
            {
                StringContent requestContent = new StringContent(dataJson, System.Text.Encoding.UTF8, "application/json");
                HttpResponseMessage response = await client.PostAsync(url, requestContent);
                if (response.IsSuccessStatusCode)
                {
                    return await response.Content.ReadAsStringAsync();
                }
                return null;
            }
        }

        /// <summary>
        /// 生成成功响应XML
        /// </summary>
        private string GetSuccessResponseXml(XElement root,string text)
        {
            var toUserName = root.Element("FromUserName")?.Value;
            var fromUserName = root.Element("ToUserName")?.Value;
            
            return $@"<xml>
                        <ToUserName><![CDATA[{toUserName}]]></ToUserName>
                        <FromUserName><![CDATA[{fromUserName}]]></FromUserName>
                        <CreateTime>{DateTimeOffset.Now.ToUnixTimeSeconds()}</CreateTime>
                        <MsgType><![CDATA[text]]></MsgType>
                        <Content><![CDATA[{text}]]></Content>
                      </xml>";
        }

        /// <summary>
        /// 解密微信加密消息
        /// </summary>
        private string DecryptMessage(string encryptedXml)
        {
            var aesKey = Convert.FromBase64String(_encodingAesKey + "=");
            var iv = new byte[16];
            Array.Copy(aesKey, iv, 16);

            using (var aes = Aes.Create())
            {
                aes.Key = aesKey;
                aes.IV = iv;
                aes.Mode = CipherMode.CBC;
                aes.Padding = PaddingMode.PKCS7;

                var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
                var encryptedData = Convert.FromBase64String(encryptedXml);
                var decryptedData = decryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
                
                var result = Encoding.UTF8.GetString(decryptedData);
                var index = result.IndexOf(_VXFWHappId);
                
                return index > 0 ? result.Substring(0, index) : result;
            }
        }
    }
}
    